ScriptX provides three primary ways in which you can directly create new objects:
4
yields an ImmediateInteger
object with the value 4.
"cat"
yields a StringConstant
object with the value "cat"
.
#(1,2,3,4)
yields an Array
object that contains four ImmediateInteger
objects with the values 1, 2, 3, and 4.
new
generic function:Function calls are discussed later in this chapter, beginning on page 63. The calling sequence for the generic functionnew
class[
key:
valuekey
:
value . . .]
new
has three components:
new
, the name of a generic function
new
method creates the instance and then passes those keyword arguments internally to the object's init
generic function. The keyword arguments that a class allows are defined by that class's init
method, and by all of its superclasses which implement an init
method.
Each class definition in the ScriptX Class Reference specifies the keyword arguments that are used by that class. Scripted classes also define keyword arguments, and they can specialize any behavior they inherit. For example, a scripted class can supply different default values for a keyword argument it inherits. For more information on specializing the init
method, see page 132.
The init
method determines which keyword arguments are optional and what the default values are. Each init
method applies the init
method defined by its superclasses. Superclasses may define other keyword arguments. The init
method may specialize or override any behavior it inherits from its superclasses. In this way, a class's init
method, together with that of its superclasses, determines which keyword arguments are defined, which are required or optional, and what the default values are.
Many classes define no keyword arguments:
myStencil := new Path
new LinkedList
If some keywords are optional, you can specify values for only the ones you are concerned with, and allow the others to be initialized to defaults:
myRect2 := new Rect x2:500 y2:500 -- x1 and y1 are set by default
bigArray := new Array initialSize:150 -- growable is set by default
Because new
evaluates to a new instance of the given class, you can nest expressions using new within other expressions:
rectangular := new TwoDShape stencil:(new Rect x2:500 y2:500)
The new Rect
expression evaluates to an instance of the Rect
class, which is then used as the value for the stencil
keyword argument to the TwoDShape
class. By nesting new
, you write more concise code and avoid extra variables.
Note that the new
generic is not a part of the ScriptX syntax. It is actually a generic function, a generic you call on class objects. Recall that in the ScriptX object system, classes are themselves objects. You can call the new
generic function on any concrete class to create an instance of that class. (Concrete and abstract classes are defined on page 23.)
For more information on new
, see the "Overview" chapter of the ScriptX Class Reference. For information on the object system, see the "Object System Kernel" chapter of ScriptX Components Guide.
new
generic for creating new instances of a class is to use the object
definition construct. The object
construct allows you to give initial values to any instance variables, including those that are not initialized by keyword arguments.
The complete form of the object
definition expression allows you to
fully specialize a new object. You can add new instance variables, define new
methods, and even create an object that is an instance of a mixture of classes.
This chapter describes only some aspects of this expression. For more
information, see Chapter 6, "Defining Classes and Objects."
The simplest form the object
expression creates a new instance of a class. Just as with new
, the object
expression allows you to specify any available or required keyword arguments:
In theobject [
variableName] (
classes)
keyword
[:
value,
keyword:
value,
. . .]
end
object
expression, classes is the class or list of classes this object is an instance of. It can be a list of several classes, separated by commas. variableName is an optional variable to which you can assign this object. The keyword:
value pairs are any keyword arguments. As with the generic function new
, you can specify keyword arguments in any order. You can specify keyword arguments on the same line, separated by commas, on separate lines, or in any combination:object (Rect) x1:35, y1:35, x2:50, y2:50 end
object (Rect)
x1:35, y1:35
x2:50, y2:50
end
object (Array)
initialSize:100
growSize:10
end
The object
expression evaluates to an instance of the new class, which allows it to be nested within other expressions. You can also assign the new object to a variable, using one of two forms: you can specify a variableName in the first line of the object
expression, or you can put the variable name on the left side of an assignment statement, with the object
expression on the right.
object myNewRect (Rect) x2:100, y2:100 end -- constant variable
myOtherNewRect := object (Rect) x2:100, y2:100 end -- not constant
The difference between these two forms is that the first form, in which you include the variable name inside the object
expression, causes the variable myNewRect
to be declared constant
. This prevents you from assigning anything else to that variable once the object has been created. You can, however, use the object
expression multiple times to redefine the object assigned to a variable.
object
expression to initialize the values of any instance variables defined by that object. In many cases, the object may use keyword arguments to give many of its instance variables initial values. However, if there are other instance variables defined by the object that are not set directly by keyword arguments, you can specify initial values for those instance variables as well.Theobject [
variableName](
classes)
keyword
[:
value,
keyword:
value,
. . .]
variable
settings
:
value
. . .
end
settings
reserved word, which should always occur just after any keyword arguments in an object
expression, indicates that the following instance variables should be initially set. You can then specify any number of variable:
value pairs. Just as with the keyword arguments, these variable:
value pairs can be specified on a single line separated by commas, on separate lines, or in any combination.
For example, the class TwoDShape
defines instance variables for its fill
and stroke
values as well as variables for the x
and y
coordinates of the shape. The init
method for TwoDShape
defines keyword arguments for fill
and stroke
, but not for the coordinates. This example uses keyword arguments to set the fill and stroke for the shape, and then settings
to initialize the values of x
and y
.
rect1 := object (TwoDShape)
fill:(new Brush color:redColor) -- keyword argument
stroke:(new Brush color:greenColor) -- keyword argument
settings
x:50, y:50
end
Many instance variables are assigned initial values through keyword arguments to the new
generic or the object
definition construct. Once the object has been created, you can use the language constructs described in these sections to get and set the values of those instance variables.
object.instanceVariableobject is an object (or an expression that yields an object), and instanceVariable is the name of the instance variable.
In the following example, a new instance of the class Line
is created. Instances of Line
have four instance variables for the coordinates of their starting and ending points: x1
, y1
and x2
, y2
. This example uses keyword arguments to set those variables, and then it accesses those values:
myLine := new Line x1:10 y1:10 x2:65 y2:65
myLine.x1
10
-- test: is the endpoint higher than the startpoint?
myLine.y2 < myLine.y1
false
If an object's instance variable holds another object that in turn has its own instance variables, you can "chain" references to those variables:
object myRectangularShape (TwoDShape)
stroke:blackBrush, boundary:(new Rect x2:100 y2:100)
end
myRectangularShape.boundary.x2
100
Note that in order to specify most complex expressions as the object part of the instance variable construct, you must specify that expression inside parentheses so that it is evaluated first. The only expressions that can be used without parentheses as the object part of an instance variable expression are:
#(1, 2, 3)
)
myArray[1]
)
myRect.x1
)
nextMethod
(described in Chapter 6, "Defining Classes and Objects)
address := odan.owner.address -- assign to a variable
for i := 1 to addressList.size do -- create a for loop to iterate over
-- an array of addresses
if addressList[i] = address do -- compare each item to variable
... -- your function for sending mail
A further efficiency could be achieved by using the Collection
method forEach
in place of the for
loop, but the for
loop is easier to understand in an example at this point.
:=
) to set the value of an instance variable:object.instanceVariable := value
As before, object is an object or an expression that yields an object, instanceVariable is the name of the instance variable, and value is an expression that sets the new value.
myLine := new Line x1:10 y1:10 x2:65 y2:65
-- Change the line's starting point to be 0,0
myLine.x1 := 0
myLine.y1 := 0
-- Change the line's endpoint to be 10,10
myLine.x2 := 10
myLine.y2 := 10
Most instance variables are read-write. That is, you can both query their values and change them. A few are read-only. If you try to change them, an error is reported. Whether an instance variable is read-write or read-only is defined by the class.
class.
varname
For example, interests
is a class variable defined by the Event
class. The result of entering the following code is a collection of the interests that have been posted in myEvent
.
myEvent.interests
Regular functions are just like functions in other languages; they have a single interface (its name and arguments), and a single implementation (the function definition), as shown in Figure 3-1.
prin
is a generic function that takes three arguments, an object to print, an argument that determines how to print it, and a stream object (prin
is described in detail on page 73). Since each class has a different printable representation, there are separate methods in each class that implement prin
. The generic function prin
uses the class of the object (myArray
, myRect
, and myString
, instances of Array
, Rect
, and String
) to choose the appropriate implementation. functionName positionalArgs keywordArgsThe first two forms are used to call regular or generic functions with arguments. Both forms are equivalent and are described below. The third form is used to call regular functions without any arguments This third form cannot be used with generic functions because they require at least one argument-the object the generic function is to operate on. The empty argument list () is used to indicate to ScriptX that this is a function call and not a variable reference.functionName
(
positionalArgs,
keywordArgs)
functionName
()
In the first two forms, positionalArgs are any required positional arguments for that function, and keywordArgs are any keyword arguments that the function or generic function may have defined. Keyword arguments are key:
value pairs, where the key and the value are separated by a colon. Positional arguments, if any, must appear before any keyword arguments and must be specified in the correct order. Keyword arguments, if any are defined, can appear in any order.
The second form for calling functions is one that may seem more familiar to those who are accustomed to other programming languages. In this form, all the arguments, positional or keyword, are separated by commas and surrounded by parentheses.
The following examples illustrate calling both regular and generic functions. These examples use the following functions:
new
generic function, as described on page 58
append
generic function, which appends an element to the end of a collection such as an array
getNth
generic function, which retrieves the element at the given position in a collection such as an array
getClassName
generic function, which returns a string containing the name of the class of which this object is an instance
helloWorld
(which takes no arguments, but prints a message to the debugging stream), and HamCheeseOnRye
, which, when called with the appropriate arguments, returns a congratulatory message. These functions do not exist as part of the the core ScriptX system and are shown for syntactic purposes only
cheez := #("swiss", "cheddar", "roquefort")
append cheez "havarti" -- returns the key of the item added to cheez
4
getNth cheez 3
"roquefort"
getNth(cheez, 4)
"havarti"
getClassName cheez
"Array"
helloWorld() -- function with no args
"Hi mom!"
hamCheeseOnRye meat:@liverwurst cheese:@swiss bread:@rye
--** "@liverwurst is not an appropriate sandwich ingredient"
hamCheeseOnRye(meat:@ham, cheese:@swiss, bread:@wholewheat)
--** "@wholewheat is not an appropriate sandwich ingredient"
hamCheeseOnRye meat:@ham cheese:@swiss bread:@rye
"a most excellent sandwich."
This document is part of the ScriptX Language Guide, one of the volumes of the ScriptX Technical Reference Series. ScriptX is developed by the ScriptX Engineering Team at Apple Computer, successor to the Kaleida Engineering Team at Kaleida Labs, Inc.